package org.opens.javaskill.audio;

import org.junit.Test;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.*;

public class PCMCovWavUtil {

    private String fileUrl = "http://39.105.193.94/ivr/87214497_1b850b88-aa59-4607-bdd4-722a9a0e624a.wav";
    private String filePath = "C:\\Users\\张玉明\\Desktop\\ivr电话客服项目\\pcm文件\\test\\aaa.wav";

    @Test
    public void test1() {
        File pcmFile = new File(filePath);
        System.out.println(pcmFile.length());
    }

    @Test
    public void test2() throws URISyntaxException, IOException {
        File file = new File("C:\\Users\\张玉明\\Desktop\\ivr电话客服项目\\pcm文件\\test\\aaa.wav");
        if(!file.exists()) {
            file.createNewFile();
        }
        FileOutputStream foo = new FileOutputStream(file);
        readUrlFile2OutputStream(fileUrl, foo);
    }

    public static File tranPcmToWavFile(File pcmFile, HttpServletRequest request, HttpServletResponse response) {
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            fis = new FileInputStream(pcmFile);
            String wavfilepath = pcmFile.getAbsolutePath().substring(0, pcmFile.getAbsolutePath().lastIndexOf(".")) + ".wav";

            String range = request.getHeader("Range");
            String[] rs = range.split("\\=");
            range = rs[1].split("\\-")[0];

            File file = new File(wavfilepath);
            if (!file.exists()) {
                file.createNewFile();
            }
            fos = new FileOutputStream(wavfilepath);

            long length = file.length();
            // 播放进度
            int count = 0;
            // 播放百分比
            int percent = (int)(length * 1);
            int irange = Integer.parseInt(range);
            length = length - irange;

            response.addHeader("Accept-Ranges", "bytes");
            response.addHeader("Content-Length", length + "");
            response.addHeader("Content-Range", "bytes " + range + "-" + length + "/" + length);
            response.addHeader("Content-Type", "audio/mpeg;charset=UTF-8");


            int PCMSize = 0;
            byte[] buf = new byte[1024 * 4];
            int size = fis.read(buf);

            while (size != -1) {
                PCMSize += size;
                size = fis.read(buf);
            }
            fis.close();



            //填入参数，比特率等等。这里用的是16位单声道 8000 hz

            WaveHeader header = new WaveHeader();
            //长度字段 = 内容的大小（PCMSize) + 头部字段的大小(不包括前面4字节的标识符RIFF以及fileLength本身的4字节)
            header.fileLength = PCMSize + (44 - 8);
            header.FmtHdrLeth = 16;
            header.BitsPerSample = 16;
            header.Channels = 1;
            header.FormatTag = 0x0001;
            header.SamplesPerSec = 8000;
            header.BlockAlign = (short) (header.Channels * header.BitsPerSample / 8);
            header.AvgBytesPerSec = header.BlockAlign * header.SamplesPerSec;
            header.DataHdrLeth = PCMSize;

            byte[] h = header.getHeader();

            assert h.length == 44; //WAV标准，头部应该是44字节
            //write header
            fos.write(h, 0, h.length);
            //write data stream
            fis = new FileInputStream(pcmFile);
            size = fis.read(buf);
            while (size != -1) {
                fos.write(buf, 0, size);
                size = fis.read(buf);
            }
            fis.close();
            fos.close();
            return new File(wavfilepath);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    public static class WaveHeader {

        public final char fileID[] = {'R', 'I', 'F', 'F'};
        public int fileLength;
        public char wavTag[] = {'W', 'A', 'V', 'E'};;
        public char FmtHdrID[] = {'f', 'm', 't', ' '};
        public int FmtHdrLeth;
        public short FormatTag;
        public short Channels;
        public int SamplesPerSec;
        public int AvgBytesPerSec;
        public short BlockAlign;
        public short BitsPerSample;
        public char DataHdrID[] = {'d','a','t','a'};
        public int DataHdrLeth;

        public byte[] getHeader() throws IOException {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            WriteChar(bos, fileID);
            WriteInt(bos, fileLength);
            WriteChar(bos, wavTag);
            WriteChar(bos, FmtHdrID);
            WriteInt(bos,FmtHdrLeth);
            WriteShort(bos,FormatTag);
            WriteShort(bos,Channels);
            WriteInt(bos,SamplesPerSec);
            WriteInt(bos,AvgBytesPerSec);
            WriteShort(bos,BlockAlign);
            WriteShort(bos,BitsPerSample);
            WriteChar(bos,DataHdrID);
            WriteInt(bos,DataHdrLeth);
            bos.flush();
            byte[] r = bos.toByteArray();
            bos.close();
            return r;
        }

        private void WriteShort(ByteArrayOutputStream bos, int s) throws IOException {
            byte[] mybyte = new byte[2];
            mybyte[1] =(byte)( (s << 16) >> 24 );
            mybyte[0] =(byte)( (s << 24) >> 24 );
            bos.write(mybyte);
        }


        private void WriteInt(ByteArrayOutputStream bos, int n) throws IOException {
            byte[] buf = new byte[4];
            buf[3] =(byte)( n >> 24 );
            buf[2] =(byte)( (n << 8) >> 24 );
            buf[1] =(byte)( (n << 16) >> 24 );
            buf[0] =(byte)( (n << 24) >> 24 );
            bos.write(buf);
        }

        private void WriteChar(ByteArrayOutputStream bos, char[] id) {
            for (int i=0; i<id.length; i++) {
                char c = id[i];
                bos.write(c);
            }
        }
    }

    private static void readUrlFile2OutputStream(String fileUrl, OutputStream outputStream) {
        BufferedInputStream bin = null;
        try {
            // 统一资源
            URL url = new URL(fileUrl);
            // 连接类的父类，抽象类
            URLConnection urlConnection = url.openConnection();
            // http的连接类
            HttpURLConnection httpURLConnection = (HttpURLConnection) urlConnection;
            //设置超时
            httpURLConnection.setConnectTimeout(1000*5);
            //设置请求方式，默认是GET
            //httpURLConnection.setRequestMethod("POST");
            // 设置字符编码
            httpURLConnection.setRequestProperty("Charset", "UTF-8");
            // 打开到此 URL引用的资源的通信链接（如果尚未建立这样的连接）。
            httpURLConnection.connect();

            // 建立链接从请求中获取数据
            URLConnection con = url.openConnection();
            bin = new BufferedInputStream(httpURLConnection.getInputStream());

            int size = 0;
            //获取远程文件的大小
            int fileLength = httpURLConnection.getContentLength();
            System.out.println(fileLength);
            byte[] buf = new byte[2048];
            while ((size = bin.read(buf)) != -1) {
                outputStream.write(buf, 0, size);
            }
            // 关闭资源
            bin.close();
            outputStream.close();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("文件下载失败！");
        } finally {
            if(bin != null) {
                try {
                    bin.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}
